/////precompiled////////
#include "precompiled.h"
////////////////////////

#include "frm.h"
using namespace frm;

// TDebug /////////////////////////////////////////////////////////////////////

int TDebug::objectsCount = 0;
TDebug::TCheck TDebug::check;

//                            
void TDebug::Check()
{
  if (objectsCount) svl::TExcept(
    svl::TString("frm::TDebug::objectsCount = ") << objectsCount
  ).Throw();
}

// TComponent /////////////////////////////////////////////////////////////////

/********************
//
bool TComponent::TType::IsInternal(const TType &Class_) 
{
  TType &Class = (TType &)Class_; TType *P = &Class.Type(); while (P)
  {
  
//svl::TString S1 = svl_ClassName(P->Type());  
//svl::TString S2 = svl_ClassName(Type());  
  
    if (&P->Type() == &Type()) { return true;}
    P = P->parent;
  }
  return false;
}
********************/

//
void TComponent::AddChildFirst(TComponent *Add,bool EnDelete)
{
  children.InsertUp(0,Add,EnDelete); 
  Add->parent = this; 
  Add->TComponent_AddToParent(this);
  TComponent_AfterAddChild(Add);
}

//
void TComponent::AddChildLast(TComponent *Add,bool EnDelete) 
{ 
  children.Add(Add,EnDelete); 
  Add->parent = this; 
  Add->TComponent_AddToParent(this);
  TComponent_AfterAddChild(Add);
}

//
void TComponent::AddChildBefore(TComponent *Add,TComponent *Curr,bool EnDelete)
{
  children.InsertUp(children.GetN(Curr),Add,EnDelete); 
  Add->parent = this; 
  Add->TComponent_AddToParent(this);
  TComponent_AfterAddChild(Add);
}

//
void TComponent::AddChildAfter(TComponent *Add,TComponent *Curr,bool EnDelete)
{
  children.InsertDn(children.GetN(Curr),Add,EnDelete); 
  Add->parent = this; 
  Add->TComponent_AddToParent(this);
  TComponent_AfterAddChild(Add);
}

static svl::TPStackEx::TStatic ST_AfterUnlinkChildren;

//
void TComponent::DeleteChildren()
{
  TComponent_BeforeDeleteChildren(); 

  bool En = ST_AfterUnlinkChildren.IsTop(NULL) && GetChildrenCount() > 0;
  svl::TPStackEx Pauc(ST_AfterUnlinkChildren,this);

  while (GetChildrenCount()) { 
    DeleteChild(0);
  }

  if (En) {
    TComponent_AfterUnlinkChildren();
  }
}

//
void TComponent::DeleteChild(int N)
{
  TComponent &Del = GetChild(N);
  bool EnDelete = children.GetEnDelete(N);

  Del.TComponent_DeleteFromParent(Del.parent);

  static svl::TPStackEx::TStatic Sbu; if (Sbu.IsTop(NULL)) {
    Del.beforeUnlinkThis();
  }
  svl::TPStackEx Pbu(Sbu,this);
  
  children.Delete(N); 

  if (ST_AfterUnlinkChildren.IsTop(NULL)) {
    TComponent_AfterUnlinkChildren();
  }
  
  if (!EnDelete) { 
    Del.parent = NULL;
  }
}

//
void TComponent::beforeUnlinkThis()
{
  for (int N = 0; N < GetChildrenCount(); N++) {
    TComponent &Child = GetChild(N);
    //Child.beforeUnlinkThis();
    Child.TComponent_BeforeUnlinkThis();
  }
}

//
void TComponent::SwapChild(TComponent *Child1,TComponent *Child2)
{
  children.SwapPObject(GetNChild(Child1),GetNChild(Child2));
}

//
void TComponent::MoveChildrenTo(int ThisNFirstChild,int ThisNLastChild,int ToNBeforeChild,TComponent *ToParent)
{
  if (children.Count()) {
    children.MoveTo(ThisNFirstChild,ThisNLastChild,ToNBeforeChild,ToParent->children);

    for (int N = 0; N < ToParent->GetChildrenCount(); N++) {
      TComponent &ToChild = ToParent->GetChild(N);
      ToChild.parent = ToParent;
    }
  }
}

//
void TComponent::PostDeleteChildren()
{
  struct TPostMessage : public svl::TPostMessage
  {
    TPostMessage(TComponent *C) { 
      c = C; Post();
    }
    virtual void TPostMessage_Receive() { 
      c->DeleteChildren();
    }
    TComponent *c;
  };
  new TPostMessage(this);
}

//
void TComponent::PostDeleteChild(TComponent *Del)
{
  struct TPostMessage : public svl::TPostMessage
  {
    TPostMessage(TComponent *C,TComponent *Child) { 
      c = C; child = Child; Post();
    }
    virtual void TPostMessage_Receive() { 
      c->DeleteChild(child);
    }
    TComponent *c; TComponent *child;
  };
  new TPostMessage(this,Del);
}

//
void TComponent::PostDeleteThis()
{
  TComponent *Parent = GetParent(); if (!Parent) {
    Except("PostDeleteThis[!Parent]");
  }
  Parent->PostDeleteChild(this);
}

//
int TComponent::CalcNumLevel()
{
  int N = -1; TComponent *P = this; while (P) {
    N++; P = P->GetParent();
  }
  return N;
}

//
bool TComponent::ThisIsParent(TComponent *Child)
{
  if (!Child) { 
    return false;
  }

  TComponent *P = Child->GetParent(); 
  
  while (P) {
    if (P == this) { 
      return true;
    }
    P = P->GetParent();
  }
  return false;
}

//
TComponent *TComponent::SearchThisOrParent(const svl::TType &TypeParent)
{
  TComponent *P = this; while (P) {
    if (((svl::TType&)TypeParent).IsInternal(P->Type())) {
      return P;
    }
    P = P->GetParent();
  }
  return NULL;
}

//
TComponent *TComponent::SearchParent(const svl::TType &TypeParent)
{
  TComponent *P = GetParent(); while (P) {
    if (((svl::TType&)TypeParent).IsInternal(P->Type())) {
      return P;
    }
    P = P->GetParent();
  }
  return NULL;
}

// TGeometryRect //////////////////////////////////////////////////////////////

//
void TGeometryRect::CopyFrom(const TGeometryRect &V_)
{
  TGeometryRect &V = (TGeometryRect&)V_;

  RParent        = V.RParent;
  RParentVisible = V.RParentVisible;

  RThis        = V.RThis;
  RThisVisible = V.RThisVisible;

  RThisClient        = V.RThisClient;
  RThisClientVisible = V.RThisClientVisible;
}

// TPaintStack ////////////////////////////////////////////////////////////////

//
TPaintStack::TPaintStack()
{
  count = 0;
}

//
TPaintStack::~TPaintStack()
{
  if (count > 0) {
    Except("~TPaintStack[count > 0]");
  }
}

//
void TPaintStack::Push(TComponent &Component,TPaint &Paint)
{
  if (count >= 200) { 
    Except("Push[count >= 200]");
  }
  TItem &Item = array[count++];
  Item.Component = &Component;
  Item.Paint     = &Paint;
}

//
TPaintStack::TItem &TPaintStack::Get(int N)
{
  if (N + 1 > count) {
    Except("Get[N + 1 > count]");
  }
  return array[N];
}

// TPaint /////////////////////////////////////////////////////////////////////

//
void TPaint::CopyFrom(const TPaint &V_)
{
  TPaint &V = (TPaint&)V_;

  DC           = V.DC;
  RClientPaint = V.RClientPaint;
  GRect        = V.GRect;
  State        = V.State;
  PaintStack   = V.PaintStack;
  //ClipRegion   = V.ClipRegion;
}

// TBorder ////////////////////////////////////////////////////////////////////

//
svl::TInfoParam TBorder::AddInfoTo(svl::TInfoParam Info) 
{ 
  svl::TString SValue; if (isNull) {
    SValue << "null";
  }
  else {
    SValue << Left << "," << Top << "," << Right << "," << Bottom;
  }

  return TPointer::AddInfoTo(Info) 
   .Add("Left,Top,Right,Bottom",SValue)
  ;
}
